// XMLSettings.h: interface for the CXMLSettings class.
//
//////////////////////////////////////////////////////////////////////

#if !defined(AFX_XMLSETTINGS_H__D979542D_EE7D_43CF_B12A_576376A88604__INCLUDED_)
#define AFX_XMLSETTINGS_H__D979542D_EE7D_43CF_B12A_576376A88604__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#include <comdef.h>

#ifndef __AFXTEMPL_H__
	#include "afxtempl.h"
#endif

#ifndef COM_API
	#ifdef COM_EXPORT
		#define COM_API __declspec( dllexport )
	#else
		#define COM_API __declspec( dllimport )
	#endif
#endif

#define XNF_NOTSAVE		0x01000000
#define XNF_NOTDELETE	0x02000000

class CXMLNode;
typedef CList<CXMLNode*, CXMLNode*> CXMLNodes;

class COM_API CXMLNode : public CObject
{
	friend class CXMLSettings;

public:
	CXMLNode()
	{
		m_pParent = NULL;
		m_dwFlag = 0;
	}

	CXMLNode(CXMLNode* pXMLNode)
	{
		m_strName = pXMLNode->m_strName;
		m_strValue= pXMLNode->m_strValue;
		m_dwFlag  = pXMLNode->m_dwFlag;
		for (POSITION pos = pXMLNode->m_lstChildren.GetHeadPosition(); pos!=NULL; )
		{
			CXMLNode* pNode = pXMLNode->m_lstChildren.GetNext (pos);
			ASSERT_VALID (pNode);
			CXMLNode* pChild = new CXMLNode(pNode);
			AddChild (pChild);
		}
	}

	~CXMLNode()
	{
		while (m_lstChildren.GetCount ())
		{
			delete m_lstChildren.RemoveHead ();
		}
	}

	static	CString m_strTab;

	CList<CXMLNode*, CXMLNode*>	m_lstChildren;
	CXMLNode*						m_pParent;

	CString	m_strName;
	CString	m_strValue;
	DWORD	m_dwFlag;

	CXMLNode* FindChild (LPCTSTR lpszName) const
	{
		for (POSITION pos = m_lstChildren.GetHeadPosition (); pos != NULL;)
		{
			CXMLNode* pNode = m_lstChildren.GetNext (pos);
			ASSERT_VALID (pNode);

			if (pNode->m_strName == lpszName)
			{
				return pNode;
			}
		}

		return NULL;
	}

	CXMLNode* FindChildNoCase (LPCTSTR lpszName) const
	{
		for (POSITION pos = m_lstChildren.GetHeadPosition (); pos != NULL;)
		{
			CXMLNode* pNode = m_lstChildren.GetNext (pos);
			ASSERT_VALID (pNode);
			
			if (pNode->m_strName.CompareNoCase(lpszName) == 0)
			{
				return pNode;
			}
		}
		
		return NULL;
	}

	CXMLNode* FindChild (LPCTSTR lpszName, POSITION& pos) const
	{
		POSITION pos0 = pos;
		for (; pos != NULL;)
		{
			CXMLNode* pNode = m_lstChildren.GetNext (pos);
			// ASSERT_VALID (pNode);
			
			if (pNode->m_strName == lpszName)
			{
				return pNode;
			}
		}

		pos = m_lstChildren.GetHeadPosition();
		for (; pos != pos0;)
		{
			CXMLNode* pNode = m_lstChildren.GetNext (pos);
			// ASSERT_VALID (pNode);
			
			if (pNode->m_strName == lpszName)
			{
				return pNode;
			}
		}
		
		return NULL;
	}

	void AddChild (CXMLNode* pNode)
	{
		m_lstChildren.AddTail (pNode);
		pNode->m_pParent = this;
	}

	BOOL GetChildsValue(CStringArray& strValues)
	{
		strValues.RemoveAll();
		for (POSITION pos = m_lstChildren.GetHeadPosition (); pos != NULL;)
		{
			CXMLNode* pNode = m_lstChildren.GetNext (pos);
			ASSERT_VALID (pNode);
			strValues.Add(pNode->m_strValue);
		}
		return TRUE;
	}

	CXMLNode* GetChild (int nIndex)
	{
		POSITION pos = m_lstChildren.FindIndex(nIndex);
		if (pos != NULL)
		{
			CXMLNode* pNode = m_lstChildren.GetNext (pos);
			ASSERT_VALID (pNode);
			return pNode;
		}
		
		return NULL;
	}
	
	void GetChildren (int nGeneration, CXMLNodes& lstChildren)
	{
		nGeneration--;
		if(nGeneration > 0)
		{
			for(POSITION pos = m_lstChildren.GetHeadPosition(); pos!=NULL; )
			{
				CXMLNode* pNode = m_lstChildren.GetNext(pos);
				ASSERT_VALID (pNode);
				pNode->GetChildren(nGeneration, lstChildren);
			}		
		}
		else
			lstChildren.AddTail(&m_lstChildren);
	}

	void AddChildren(CXMLNodes* pChildren)
	{
		POSITION pos = pChildren->GetHeadPosition();
		for ( ; pos != NULL; )
		{
			CXMLNode* pAddChild = pChildren->GetNext(pos);
			CXMLNode* pChild = FindChild(pAddChild->m_strName);
			if (pChild != NULL)
			{
				// pChild->m_dwFlag = pAddChild->m_dwFlag;
				pChild->m_strValue = pAddChild->m_strValue;
				pChild->AddChildren(&pAddChild->m_lstChildren);
				pAddChild->m_lstChildren.RemoveAll();
				delete pAddChild;
			}
			else
				AddChild(pAddChild);
		}
	}

	void AddNewChildren(CXMLNodes* pChildren)
	{
		POSITION pos = pChildren->GetHeadPosition();
		for ( ; pos != NULL; )
		{
			CXMLNode* pAddChild = pChildren->GetNext(pos);
			CXMLNode* pChild = new CXMLNode(pAddChild);
			AddChild(pChild);
		}
	}

	void Prev()
	{
		if (m_pParent != NULL)
		{
			POSITION pos0 = m_pParent->m_lstChildren.Find(this);
			POSITION pos1 = pos0;
			m_pParent->m_lstChildren.GetPrev(pos1);
			if (pos1 != NULL)
			{
				m_pParent->m_lstChildren.InsertBefore(pos1, this);
				m_pParent->m_lstChildren.RemoveAt(pos0);
			}
		}
	}

	void Next()
	{
		if (m_pParent != NULL)
		{
			POSITION pos0 = m_pParent->m_lstChildren.Find(this);
			POSITION pos1 = pos0;
			m_pParent->m_lstChildren.GetNext(pos1);
			if (pos1 != NULL)
			{
				m_pParent->m_lstChildren.InsertAfter(pos1, this);
				m_pParent->m_lstChildren.RemoveAt(pos0);
			}
		}
	}

	int WriteToBuffer (CString& strBuffer, int iOffset);
	int WriteToBuffer (CString& strBuffer, int iOffset, int iLevel);
	int	WriteToText (CStdioFile& file, CString& strBuffer);
	BOOL ReadFromBuffer (CString& strBuffer);
	BOOL ReadFromBuffer2 (CString& strBuffer, CStringList* pList);
	BOOL RereadFromBuffer (CString& strBuffer);
	BOOL ReadFromBuffer (CString& strBuffer, LPCTSTR lpszPath);
};

class COM_API CXMLSettings : public CObject
{
public:
	CXMLSettings(BOOL bReadOnly = TRUE, LPCTSTR lpszRoot = _T(""));
	virtual ~CXMLSettings();

// Attributes:
public:
	CXMLNode	m_Local;		// "CURRENT_USER"
	CXMLNode*	m_pCurrNode;	// Current node
	BOOL		m_bReadOnly;	// Read or write mode
	POSITION	m_posChild;		// Position of current node's child
	CString		m_sPath;
protected:
//	CString		m_sPath;

// Operations
public:
	virtual CXMLNode* GetTree ();
	BOOL IsLoading() const { return m_bReadOnly;	}
	BOOL IsStoring() const { return !m_bReadOnly;	}

	void SetCurrNode(CXMLNode* pNode)
	{
		m_pCurrNode = pNode;
		if (m_pCurrNode)
			m_posChild = m_pCurrNode->m_lstChildren.GetHeadPosition();
	}

	BOOL WriteXMLToFile (LPCTSTR lpszFileName);
	BOOL WriteCurrNodeToFile (LPCTSTR lpszFileName);
	BOOL ReadXMLFromFile (LPCTSTR lpszFileName);
	BOOL RereadXMLFromFile (LPCTSTR lpszFileName);
	BOOL ReadCurrNodeFromFile (LPCTSTR lpszFileName, BOOL bRebuild = TRUE);
	BOOL ReadXMLFromFile (LPCTSTR lpszFileName, LPCTSTR lpszKey);

	BOOL WriteXMLToText	(LPCTSTR lpszTextName);

	BOOL WriteXMLToStream (IStreamPtr& pStream);
	BOOL RereadXMLFromStream (IStreamPtr& pStream);
	BOOL ReadXMLFromStream (IStreamPtr& pStream, LPCTSTR pszKey = NULL);
	BOOL ReadXMLFromStream (IStreamPtr& pStream, LPCTSTR pszKey0, LPCTSTR pszKey1);

	BOOL WriteXMLToBuffer (CString& strBuffer);
	BOOL ReadXMLFromBuffer (CString& strBuffer);
	BOOL WriteXMLToFile (CFile* pFile);
	BOOL ReadXMLFromFile (CFile* pFile);
	BOOL ReadXMLFromFile (CFile* pFile, LPCTSTR pszKey0, LPCTSTR pszKey1);
	BOOL GetChildFromFile (CFile* pFile);
	BOOL WriteXMLToFiles (CFile* pFile0, ...);

	BOOL ReadKeyValues(CStringArray& Values);
	BOOL VerifyKey (LPCTSTR pszPath);
	BOOL VerifyValue (LPCTSTR pszValue);
	BOOL CreateKey (LPCTSTR pszPath);
	BOOL CreateKey (LPCTSTR lpszFormat, UINT uiID);
	BOOL Open (LPCTSTR pszPath);
	BOOL OpenNoCase (LPCTSTR pszPath);
	BOOL Open (LPCTSTR lpszFormat, UINT uiID);
	BOOL Back (int nLevel = 1);
	BOOL Go (int first, ...);
	void Close();

	BOOL DeleteValue (LPCTSTR pszValue);
	BOOL DeleteKey (LPCTSTR pszPath);
	BOOL DeleteAllKeys ();
	BOOL DeleteCurrNodeChildKeys(BOOL bAll = TRUE);

	BOOL Write (LPCTSTR pszKey, int iVal);
	BOOL Write (LPCTSTR pszKey, DWORD dwVal);
	BOOL Write (LPCTSTR pszKey, LPCTSTR pszVal);
	BOOL Write (LPCTSTR pszKey, CWordArray& wcArray);
	BOOL Write (LPCTSTR pszKey, const CRect& rect);
	BOOL Write (LPCTSTR pszKey, const CPoint& point);
	BOOL Write (LPCTSTR pszKey, const CSize& size);
	BOOL Write (LPCTSTR pszKey, short& sValue);
	BOOL Write (LPCTSTR pszKey, long& lValue);
	BOOL Write (LPCTSTR pszKey, float& fValue);
	BOOL Write (LPCTSTR pszKey, double& dValue);
	BOOL Write (LPCTSTR pszKey, UINT& uiValue);
	BOOL Write (LPCTSTR pszKey, USHORT& usValue);
	BOOL Write (LPCTSTR pszKey, LPBYTE pData, UINT nBytes);
	BOOL Write (LPCTSTR pszKey, VARIANT& data);
	BOOL Write (LPCTSTR pszKey, CObject& obj);
	BOOL Write (LPCTSTR pszKey, CObject* pObj);

	BOOL Read (LPCTSTR pszKey, int& iVal);
	BOOL Read (LPCTSTR pszKey, DWORD& dwVal);
	BOOL Read (LPCTSTR pszKey, CString& sVal);
	BOOL Read (LPCTSTR pszKey, CWordArray& wcArray);
	BOOL Read (LPCTSTR pszKey, CPoint& point);
	BOOL Read (LPCTSTR pszKey, CRect& rect);
	BOOL Read (LPCTSTR pszKey, CSize& size);
	BOOL Read (LPCTSTR pszKey, short& sValue);
	BOOL Read (LPCTSTR pszKey, long& lValue);
	BOOL Read (LPCTSTR pszKey, float& fValue);
	BOOL Read (LPCTSTR pszKey, double& dValue);
	BOOL Read (LPCTSTR pszKey, UINT& uiValue);
	BOOL Read (LPCTSTR pszKey, USHORT& usValue);
	BOOL Read (LPCTSTR pszKey, BYTE** ppData, UINT* pBytes);
	BOOL Read (LPCTSTR pszKey, VARIANT& data);
	BOOL Read (LPCTSTR pszKey, LPBYTE pData, UINT& nBytes);
	BOOL Read (LPCTSTR pszKey, CObject& obj);
	BOOL Read (LPCTSTR pszKey, CObject*& pObj);

	BOOL ReadSubKeys(CStringList& SubKeys);

protected:
	BOOL WriteTag (LPCTSTR pszKey, LPCTSTR lpszBuffer);
	LPCTSTR ReadTag (LPCTSTR pszKey) const;


public:
	BOOL Read(CString &sVal);
	BOOL OpenNext(LPCTSTR pszPath);
	BOOL Write (UINT uiID, LPCTSTR pszKey, int iVal)
	{
		CString strKey;
		strKey.Format(pszKey, uiID);
		return Write(strKey, iVal);
	}

	BOOL Write (UINT uiID, LPCTSTR pszKey, DWORD dwVal)
	{
		CString strKey;
		strKey.Format(pszKey, uiID);
		return Write(strKey, dwVal);
	}

	BOOL Write (UINT uiID, LPCTSTR pszKey, LPCTSTR pszVal)
	{
		CString strKey;
		strKey.Format(pszKey, uiID);
		return Write(strKey, pszVal);
	}

	BOOL Write (UINT uiID, LPCTSTR pszKey, CWordArray& wcArray)
	{
		CString strKey;
		strKey.Format(pszKey, uiID);
		return Write(strKey, wcArray);
	}

	BOOL Write (UINT uiID, LPCTSTR pszKey, const CRect& rect)
	{
		CString strKey;
		strKey.Format(pszKey, uiID);
		return Write(strKey, rect);
	}

	BOOL Write (UINT uiID, LPCTSTR pszKey, const CPoint& lpPoint)
	{
		CString strKey;
		strKey.Format(pszKey, uiID);
		return Write(strKey, lpPoint);
	}

	BOOL Write (UINT uiID, LPCTSTR pszKey, const CSize& size)
	{
		CString strKey;
		strKey.Format(pszKey, uiID);
		return Write(strKey, size);
	}

	BOOL Write (UINT uiID, LPCTSTR pszKey, long& lValue)
	{
		CString strKey;
		strKey.Format(pszKey, uiID);
		return Write(strKey, lValue);
	}

	BOOL Write (UINT uiID, LPCTSTR pszKey, float& fValue)
	{
		CString strKey;
		strKey.Format(pszKey, uiID);
		return Write(strKey, fValue);
	}

	BOOL Write (UINT uiID, LPCTSTR pszKey, double& dValue)
	{
		CString strKey;
		strKey.Format(pszKey, uiID);
		return Write(strKey, dValue);
	}

	BOOL Write (UINT uiID, LPCTSTR pszKey, UINT& uiValue)
	{
		CString strKey;
		strKey.Format(pszKey, uiID);
		return Write(strKey, uiValue);
	}

	BOOL Write (UINT uiID, LPCTSTR pszKey, USHORT& usValue)
	{
		CString strKey;
		strKey.Format(pszKey, uiID);
		return Write(strKey, usValue);
	}

	BOOL Write (UINT uiID, LPCTSTR pszKey, LPBYTE pData, UINT nBytes)
	{
		CString strKey;
		strKey.Format(pszKey, uiID);
		return Write(strKey, pData, nBytes);
	}

	BOOL Write (UINT uiID, LPCTSTR pszKey, CObject& obj)
	{
		CString strKey;
		strKey.Format(pszKey, uiID);
		return Write(strKey, obj);
	}

	BOOL Write (UINT uiID, LPCTSTR pszKey, CObject* pObj)
	{
		CString strKey;
		strKey.Format(pszKey, uiID);
		return Write(strKey, pObj);
	}

	BOOL Read (UINT uiID, LPCTSTR pszKey, int& iVal)
	{
		CString strKey;
		strKey.Format(pszKey, uiID);
		return Read(strKey, iVal);
	}

	BOOL Read (UINT uiID, LPCTSTR pszKey, DWORD& dwVal)
	{
		CString strKey;
		strKey.Format(pszKey, uiID);
		return Read(strKey, dwVal);
	}

	BOOL Read (UINT uiID, LPCTSTR pszKey, CString& sVal)
	{
		CString strKey;
		strKey.Format(pszKey, uiID);
		return Read(strKey, sVal);
	}

	BOOL Read (UINT uiID, LPCTSTR pszKey, CWordArray& wcArray)
	{
		CString strKey;
		strKey.Format(pszKey, uiID);
		return Read(strKey, wcArray);
	}

	BOOL Read (UINT uiID, LPCTSTR pszKey, CPoint& lpPoint)
	{
		CString strKey;
		strKey.Format(pszKey, uiID);
		return Read(strKey, lpPoint);
	}

	BOOL Read (UINT uiID, LPCTSTR pszKey, CRect& rect)
	{
		CString strKey;
		strKey.Format(pszKey, uiID);
		return Read(strKey, rect);
	}

	BOOL Read (UINT uiID, LPCTSTR pszKey, CSize& size)
	{
		CString strKey;
		strKey.Format(pszKey, uiID);
		return Read(strKey, size);
	}

	BOOL Read (UINT uiID, LPCTSTR pszKey, long& lValue)
	{
		CString strKey;
		strKey.Format(pszKey, uiID);
		return Read(strKey, lValue);
	}

	BOOL Read (UINT uiID, LPCTSTR pszKey, float& fValue)
	{
		CString strKey;
		strKey.Format(pszKey, uiID);
		return Read(strKey, fValue);
	}

	BOOL Read (UINT uiID, LPCTSTR pszKey, double& dValue)
	{
		CString strKey;
		strKey.Format(pszKey, uiID);
		return Read(strKey, dValue);
	}

	BOOL Read (UINT uiID, LPCTSTR pszKey, UINT& uiValue)
	{
		CString strKey;
		strKey.Format(pszKey, uiID);
		return Read(strKey, uiValue);
	}

	BOOL Read (UINT uiID, LPCTSTR pszKey, USHORT& usValue)
	{
		CString strKey;
		strKey.Format(pszKey, uiID);
		return Read(strKey, usValue);
	}

	BOOL Read (UINT uiID, LPCTSTR pszKey, LPBYTE pData, UINT& nBytes)
	{
		CString strKey;
		strKey.Format(pszKey, uiID);
		return Read(strKey, pData, nBytes);
	}

	BOOL Read (UINT uiID, LPCTSTR pszKey, CObject& obj)
	{
		CString strKey;
		strKey.Format(pszKey, uiID);
		return Read(strKey, obj);
	}

	BOOL Read (UINT uiID, LPCTSTR pszKey, CObject*& pObj)
	{
		CString strKey;
		strKey.Format(pszKey, uiID);
		return Read(strKey, pObj);
	}
};

extern BOOL ExcludeTag(CString& strBuffer, LPCTSTR lpszTag, CString& strTag);
extern BOOL ExcludeTag2(CString& strBuffer, CStringList* pList, CString& strTag);
extern BOOL ExcludeTag3(CString& strBuffer, CStringList* pList, CString& strTag);

#endif // !defined(AFX_XMLSETTINGS_H__D979542D_EE7D_43CF_B12A_576376A88604__INCLUDED_)
